/*************************************************************************
 * Filename:    Queue.c
 * Description: This program is a generic queue. It supports simple queue
 *              operations like enqueue, dequeue and delete.
 * Group 3:     nachOS
 * Authors:     Ying Wang
 *              
 * Class:       CSE 325
 * Instructor:  Mr. Duggan
 * Assignment:  Lab #1 Queue Manager
 * Assigned:    January 22, 2013
 * Due:         January 29, 2013
 *************************************************************************/

#include "Queue.h"

/**
 * Enqueues a queue_item to the specified queue.
 * @author Ying Wang
 * @param queue* The queue in which to enqueue the specified item.
 * @param queue_item* The item to enqueue to the specified queue.
 * @returns void
 */
void enqueue(queue* queue, queue_item* item){
    // if it's an empty queue, point both head and tail to the queue_item and increment the length.
    if(queue->length==0){
        queue->head = item;
        queue->tail = item;
        queue->tail->next = 0;
        queue->length++;
    }
    
    // if it's not an empty queue, adjust the tail pointer and increment the length.
    else{                          
        queue->tail->next = item;
        item->previous = queue->tail;
        queue->tail = item;
        queue->tail->next = 0;
        queue->length++;
    }    
}

/**
 * Dequeues the oldest queue_item from the specified queue.
 * @author Ying Wang
 * @param queue* Tonhe queue from which to dequeue the oldest item.
 * @returns int 1 on success and -1 on error
 */
int dequeue(queue* queue){
    // if it's an empty queue, it should return an error indicated by "-1".
    if(queue->length==0){
        return -1;
    }
    
    // if there's only one item in the queue, change both head and tail to 0, and the queue length to 0.
    else if(queue->length==1){                               
        queue->head = 0;
        queue->tail = 0;
        queue->length = 0;         
        return 1;                  // send a positive signal
    }
    
    // if it's not an empty queue, adjust the head pointer and the length.
    else{                         
        queue_item* temp = queue->head;
        temp->next->previous = 0;
        queue->head = temp->next;
        temp->next = 0;
        queue->length--;           // decrement the queue length
        return 1;                  // send a positive signal
    }
}

/**
 * Deletes the specific queue_item from the specified queue. Note: it assumes that the queue_item exists in the queue.
 * @author Ying Wang
 * @param queue* The queue from which to delete the specified item.
 * @param queue_item* The item to delete from the specified queue.
 * @returns void
 */
void delete(queue* queue, queue_item* item){
    // if the queue_item to be deleted is the only item in the queue, change both head and tail to 0.
    if(queue->length==1){
        queue->head = 0;
        queue->tail = 0;
        queue->length = 0;         // decrement the queue length
    }
    
    // if the queue_item to be deleted is the head of the queue, it's the same as dequeue
    else if(queue->head==item){
        dequeue(queue);
    }
    
    // if the queue_item to be deleted is the tail of the queue, adjust the tail pointer
    else if(queue->tail==item){
        queue_item* temp = queue->tail;
        queue->tail = queue->tail->previous;
        temp->previous = 0;
        queue->tail->next = 0;
        queue->length--;           // decrement the queue length
    }
    
    // if the queue_item to be deleted is in the middle of the queue, adjust the pointers of the previous item and the next item
    else{                         
        item->previous->next = item->next;
        item->next->previous = item->previous;
        item->previous = 0;     // release the current item by setting its pointers to 0
        item->next = 0;
        queue->length--;           // decrement the queue length
    }
}
